﻿using Yxinmt.Interface;
using Yxinmt.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace Yxinmt.Controls
{
    public class VlcPlayer : BaseControl, IControl
    {
        private System.Windows.Controls.Grid _Grid { get; set; }
        private System.Windows.Controls.Grid _Grid2 { get; set; }

        static Vlc.DotNet.Wpf.VlcControl _VlcControl { get; set; }

        System.Windows.Controls.DockPanel _BottomPanel { get; set; }

        System.Windows.Controls.ContentControl _ContentControl { get; set; }

        System.Windows.Forms.Integration.WindowsFormsHost _WpfWindowsFormsHost { get; set; }

        public VlcPlayer(Dictionary<string, object> property, IComponent component, bool isFactory = false)
        {
            Property = property;
            _Component = component;

            _Grid = new System.Windows.Controls.Grid();
            _Grid2 = new System.Windows.Controls.Grid();
            _Grid.Children.Add(_Grid2);
            this.Element = _Grid;

            InitSet();
            this.SetProperty();
            this.SetControlProperty(false, false);
        }
        private DirectoryInfo _VlcLibDirectory { get; set; }

        private void SetProperty()
        {
            _VlcLibDirectory = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64"));

            _ContentControl = new System.Windows.Controls.ContentControl();
            _VlcPlayerList.Add(this);
            SetZIndex(1);
            _Grid2.Children.Add(_ContentControl);

            _WpfWindowsFormsHost = new System.Windows.Forms.Integration.WindowsFormsHost();
            SetZIndex(2);
            _Grid2.Children.Add(_WpfWindowsFormsHost);

            _BottomPanel = new System.Windows.Controls.DockPanel();
            _BottomPanel.Height = 40;
            _BottomPanel.Background = GetColor("#000000");
            _BottomPanel.Opacity = 0.5;
            _BottomPanel.VerticalAlignment = System.Windows.VerticalAlignment.Bottom;
            _BottomPanel.Visibility = System.Windows.Visibility.Hidden;
            SetZIndex(3);
            InitBottomPanel();

            _Grid2.Children.Add(_BottomPanel);
        }

        public Action CloseAction { get; set; }
        void InitBottomPanel()
        {
            Dictionary<string, object> dict = new Dictionary<string, object>();
            dict.Add("Name", this.Name + "Play");
            dict.Add("Label", "播放");
            dict.Add("PanelType", "DockPanel");
            dict.Add("Width", 60);
            dict.Add("Height", 40);
            dict.Add("Dock", "Left");
            dict.Add("TextAlign", "MiddleCenter");
            dict.Add("FontSize", "20");
            dict.Add("FontColor", "#ffffff");
            dict.Add("BackColor", "#000000");

            _PlayButton = new ImageTextButton(dict, _Component);
            _PlayButton.ClickAction = (sender, e, ctl) => PlayClick(sender, e);

            _BottomPanel.Children.Add(_PlayButton.Element);


            dict = new Dictionary<string, object>();
            dict.Add("Name", this.Name + "Close");
            dict.Add("PanelType", "DockPanel");
            dict.Add("Label", "关闭");
            dict.Add("Width", 60);
            dict.Add("Height", 40);
            dict.Add("Dock", "Right");
            dict.Add("TextAlign", "MiddleCenter");
            dict.Add("FontSize", "20");
            dict.Add("FontColor", "#ffffff");
            dict.Add("BackColor", "#000000");

            _CloseButton = new ImageTextButton(dict, _Component);
            _CloseButton.ClickAction = (sender, e, ctl) =>
            {
                if (CloseAction != null) CloseAction();
                Close();
            };
            _BottomPanel.Children.Add(_CloseButton.Element);

            dict = new Dictionary<string, object>();
            dict.Add("Name", this.Name + "FullScreen");
            dict.Add("PanelType", "DockPanel");
            dict.Add("Label", "全屏");
            dict.Add("Width", 60);
            dict.Add("Height", 40);
            dict.Add("Dock", "Right");
            dict.Add("TextAlign", "MiddleCenter");
            dict.Add("FontSize", "20");
            dict.Add("FontColor", "#ffffff");
            dict.Add("BackColor", "#000000");
            _FullScreenButton = new ImageTextButton(dict, _Component);
            _FullScreenButton.ClickAction = (sender, e, ctl) =>
            {
                SetFullScreen();
                if (SysncFullScreen != null) SysncFullScreen(IsFullScreen);
            };
            _BottomPanel.Children.Add(_FullScreenButton.Element);

            dict = new Dictionary<string, object>();
            dict.Add("Name", this.Name + "Time");
            dict.Add("LabelWidth", 120);
            dict.Add("Height", 40);
            dict.Add("Dock", "Right");
            dict.Add("FontSize", "20");
            dict.Add("FontColor", "#ffffff");
            dict.Add("Text", "00:00/00:00");
            dict.Add("TextAlign", "MiddleCenter");

            _TimeLabel = new Label(dict, _Component);

            _BottomPanel.Children.Add(_TimeLabel.Element);


            _TimeSlider = new System.Windows.Controls.Slider();
            _TimeSlider.Margin = new System.Windows.Thickness(0, 12, 0, 0);
            this._TimeSlider.IsEnabled = false;
            _BottomPanel.Children.Add(_TimeSlider);

            _BottomPanel.Margin = new System.Windows.Thickness(0, 0, 0, 2);
        }


        void PlayClick(object sender, System.Windows.RoutedEventArgs e)
        {
            if (_VlcControl == null) { Play(_Url, _IsLive); _PlayButton.SetLabelText("暂停"); }
            else if (_VlcControl.SourceProvider.MediaPlayer.State == Vlc.DotNet.Core.Interops.Signatures.MediaStates.Playing
                || _VlcControl.SourceProvider.MediaPlayer.State == Vlc.DotNet.Core.Interops.Signatures.MediaStates.Paused)
            {
                if (_VlcControl.SourceProvider.MediaPlayer.State == Vlc.DotNet.Core.Interops.Signatures.MediaStates.Playing)
                {
                    Pause();
                    _PlayButton.SetLabelText("播放");
                }
                else if (_VlcControl.SourceProvider.MediaPlayer.State == Vlc.DotNet.Core.Interops.Signatures.MediaStates.Paused)
                {
                    Play();
                    _PlayButton.SetLabelText("暂停");
                }
            }

            SetVisibleBottom();
        }

        Controls.ImageTextButton _PlayButton { get; set; }
        Controls.Label _TimeLabel { get; set; }

        System.Windows.Controls.Slider _TimeSlider { get; set; }

        static List<VlcPlayer> _VlcPlayerList { get; set; }

        static VlcPlayer()
        {
            _VlcPlayerList = new List<VlcPlayer>();
        }

        public static void Dispose()
        {
            _VlcPlayerList.ForEach(c =>
            {
                c.Close();
            });
            Task.Run(() =>
            {
                try
                {
                    if (_VlcControl != null)
                    {
                        _VlcControl.Dispose();
                        _VlcControl = null;
                    }
                }
                catch { }
            });
        }

        public override void DataLoad()
        {
            base.DataLoad();
        }

        string _Url { get; set; }

        bool _IsLive { get; set; }

        object _lock = new object();
        

        Controls.PictureBoxPlayer _PictureBoxPlayer { get; set; }

        public void PlayLive(string url, IWindow win, IControl statusCtl, string statusName)
        {
            _IsLive = true;
            lock (_lock)
            {
                if (_VlcControl != null)
                {
                    _VlcControl.Dispose();
                    _VlcControl = null;
                }

                _Grid.Visibility = System.Windows.Visibility.Visible;

                _ContentControl.Visibility = Visibility.Collapsed;
                _WpfWindowsFormsHost.Visibility = Visibility.Visible;
                _WpfWindowsFormsHost.Width = _Grid.ActualWidth;
                _WpfWindowsFormsHost.Height = _Grid.ActualHeight;

                Dictionary<string, object> dict = new Dictionary<string, object>();
                dict["Name"] = "PictureBoxPlayer1";
                _PictureBoxPlayer = new Controls.PictureBoxPlayer(dict, win);
                _PictureBoxPlayer.InitSetStatus(statusCtl, statusName);
                _PictureBoxPlayer.IsFullScreen = IsFullScreen;
                _PictureBoxPlayer.InitControl(_WpfWindowsFormsHost);
                _PictureBoxPlayer.Play(url);
                _PictureBoxPlayer.SetFullScreen = (isFullScreen) =>
                {
                    IsFullScreen = isFullScreen;
                    if (SysncFullScreen != null) SysncFullScreen(IsFullScreen);
                };

                _IsClosed = false;
            }
        }

        public void Play(string url, bool isLive)
        {
            lock (_lock)
            {
                if (isLive && url == _Url) return;
                _IsLive = isLive;
                _Url = url;

                if (_IsLive || url.ToLower().StartsWith("http"))
                {
                    if (_VlcControl != null)
                    {
                        _VlcControl.Dispose();
                        _VlcControl = null;
                    }
                }

                if (_VlcControl == null)
                {
                    _VlcControl = new Vlc.DotNet.Wpf.VlcControl();
                    _VlcControl.SourceProvider.CreatePlayer(this._VlcLibDirectory);

                    _VlcControl.SourceProvider.MediaPlayer.TimeChanged += MediaPlayer_TimeChanged;
                    _VlcControl.SourceProvider.MediaPlayer.Buffering += MediaPlayer_Buffering;
                    _VlcControl.SourceProvider.MediaPlayer.EndReached += MediaPlayer_EndReached;
                }

                _ContentControl.Visibility = Visibility.Visible;
                _WpfWindowsFormsHost.Visibility = Visibility.Collapsed;

                this._ContentControl.Content = _VlcControl;
                _VlcControl.SourceProvider.MediaPlayer.Play(new Uri(url));
                _IsClosed = false;
                if (!isLive)
                {
                    this._TimeLabel.SetValue("00:00/00:00");
                    _TimeSlider.IsEnabled = true;
                }
                else
                {
                    this._TimeLabel.SetValue("直播");
                    _TimeSlider.Value = 0;
                    _TimeSlider.IsEnabled = false;
                }

                _Grid.Visibility = System.Windows.Visibility.Visible;
                _BottomPanel.Visibility = System.Windows.Visibility.Visible;

                SetHideBottom();
            }
        }

        private void MediaPlayer_EndReached(object sender, Vlc.DotNet.Core.VlcMediaPlayerEndReachedEventArgs e)
        {
            if (_IsLive) return;
            Task.Run(() =>
            {
                Thread.Sleep(1000);
                this._Window.Window.Dispatcher.Invoke(() =>
                {
                    Play(_Url, _IsLive);
                });
            });
        }

        private void MediaPlayer_Buffering(object sender, Vlc.DotNet.Core.VlcMediaPlayerBufferingEventArgs e)
        {
            if (_IsLive) return;
            this._Window.Window.Dispatcher.Invoke(() =>
            {
                this._TimeLabel.SetValue("正在缓冲……");
                SetVisibleBottom();
            });
        }

        private void MediaPlayer_TimeChanged(object sender, Vlc.DotNet.Core.VlcMediaPlayerTimeChangedEventArgs e)
        {
            if (_IsLive) return;
            try
            {
                this._Window.Window.Dispatcher.Invoke(() =>
                {
                    if (_VlcControl == null) return;
                    long len = _VlcControl.SourceProvider.MediaPlayer.Length;
                    long length = 0;

                    if (len % 1000 == 0) length = len / 1000;
                    else length = len / 1000 + 1;

                    long newTime = 0;

                    if (e.NewTime % 1000 == 0) newTime = e.NewTime / 1000;
                    else newTime = e.NewTime / 1000 + 1;

                    if (!_MouseDown)
                    {
                        this._TimeSlider.Maximum = length;
                        this._TimeSlider.Minimum = 0;
                        this._TimeSlider.Value = newTime;
                    }

                    if (!this._TimeSlider.IsEnabled) this._TimeSlider.IsEnabled = true;

                    if (!_PlayButton.GetLabelText().Equals("暂停"))
                    {
                        _PlayButton.SetLabelText("暂停");
                    }

                    long mm = length / 60;
                    long ss = (length - mm * 60);

                    long mm2 = newTime / 60;
                    long ss2 = (newTime - mm2 * 60);

                    string mmStr = mm < 10 ? "0" + mm.ToString() : mm.ToString();
                    string ssStr = ss < 10 ? "0" + ss.ToString() : ss.ToString();
                    string mmStr2 = mm2 < 10 ? "0" + mm2.ToString() : mm2.ToString();
                    string ssStr2 = ss2 < 10 ? "0" + ss2.ToString() : ss2.ToString();

                    _TimeLabel.SetValue(string.Format("{0}:{1}/{2}:{3}", mmStr, ssStr, mmStr2, ssStr2));
                });
            }
            catch
            {

            }
        }

        CancellationTokenSource _SetHideBootomCanckTask { get; set; }

        void SetHideBottom()
        {
            if (_SetHideBootomCanckTask != null)
            {
                _SetHideBootomCanckTask.Cancel();
                _SetHideBootomCanckTask.Dispose();
                _SetHideBootomCanckTask = null;
            }

            _SetHideBootomCanckTask = new CancellationTokenSource();

            Task.Run(() =>
            {
                while (_VlcControl != null && _SetHideBootomCanckTask!=null && !_SetHideBootomCanckTask.IsCancellationRequested)
                {
                    Thread.Sleep(5000);

                    if (_EndTime.AddSeconds(5) < DateTime.Now)
                    {
                        this._Window.Window.Dispatcher.Invoke(() =>
                        {
                            _BottomPanel.Visibility = System.Windows.Visibility.Collapsed;
                        });
                    }
                }
            }, _SetHideBootomCanckTask.Token);
        }

        bool _MouseDown = false;
        void Slider_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            SetVisibleBottom();
            this._MouseDown = true;
        }

        private void Slider_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (_MouseDown)
            {
                _VlcControl.SourceProvider.MediaPlayer.Time = ((long)this._TimeSlider.Value) * 1000;
                _MouseDown = false;
                SetVisibleBottom();
            }
        }

        public void Pause()
        {
            if (_VlcControl == null || _VlcControl.SourceProvider.MediaPlayer == null) return;
            _VlcControl.SourceProvider.MediaPlayer.SetPause(true);
        }

        public void Play()
        {
            if (_VlcControl == null || _VlcControl.SourceProvider.MediaPlayer == null) return;
            _VlcControl.SourceProvider.MediaPlayer.SetPause(false);
        }


        public Action CloseVideo { get; set; }

        bool _IsClosed { get; set; }

        public void Close()
        {
            lock (_lock)
            {
                try
                {
                    if (_VlcControl != null && !_IsClosed)
                    {
                        _IsClosed = true;
                        try
                        {
                            CloseFullScreen();
                            Pause();

                            if (_VlcControl.SourceProvider.MediaPlayer != null) _VlcControl.SourceProvider.MediaPlayer.Play(string.Empty);
                        }
                        catch
                        {
                        }
                        if (_SetHideBootomCanckTask != null)
                        {
                            _SetHideBootomCanckTask.Cancel();
                            _SetHideBootomCanckTask.Dispose();
                            _SetHideBootomCanckTask = null;
                        }
                        Thread.Sleep(200);
                        _Grid.Visibility = System.Windows.Visibility.Collapsed;
                        if (CloseVideo != null) CloseVideo();
                    }

                    if (_PictureBoxPlayer != null)
                    {
                        _IsClosed = true;
                        _PictureBoxPlayer.Stop();
                        _PictureBoxPlayer = null;

                        if (_SetHideBootomCanckTask != null)
                        {
                            _SetHideBootomCanckTask.Cancel();
                            _SetHideBootomCanckTask.Dispose();
                            _SetHideBootomCanckTask = null;
                        }

                        if (CloseVideo != null) CloseVideo();

                        _Grid.Visibility = System.Windows.Visibility.Collapsed;
                    }
                }
                catch
                {

                }
            }
        }

        protected override void SetProperty(string name, object value)
        {
            System.Windows.Controls.Grid c = _Grid;
            switch (name)
            {
                case "Name": c.Name = string.Concat("grid_", (string)value); SetFactoryProperty("Name", c.Name); break;
                case "Height": c.Height = Convert.ToDouble(value); SetFactoryProperty("Height", c.Height); break;
                case "Width": c.Width = Convert.ToDouble(value); SetFactoryProperty("Width", c.Width); break;
                case "Dock": System.Windows.Controls.DockPanel.SetDock(c, this.GetDock((string)value)); break;
                case "BackColor": c.Background = GetColor((string)value); SetFactoryProperty("Background", c.Background); break;
                case "ControlAlign": SetControlAlign((string)value); break;
                case "Visible": SetVisible((bool)value); break;
                case "GridRowColumn": SetGridRowColumn((string)value); break;
                case "BackImageUrl": SetBackgroundImage((string)value); break;
                case "ZIndex": SetZIndex((int)value); break;
                case "CanvasLocation": SetCanvasLocation((string)value); break;
                case "CanvasZIndex": SetCanvasZIndex((int)value); break;
                case "Margin": c.Margin = this.GetThickness((string)value); SetFactoryProperty("Margin", c.Margin); break;
            }
        }

        public override void EventLoad()
        {
            base.EventLoad();

            this._TimeSlider.AddHandler(System.Windows.Controls.Slider.MouseLeftButtonUpEvent, new System.Windows.Input.MouseButtonEventHandler(Slider_MouseLeftButtonUp), true);
            this._TimeSlider.AddHandler(System.Windows.Controls.Slider.MouseLeftButtonDownEvent, new System.Windows.Input.MouseButtonEventHandler(Slider_MouseLeftButtonDown), true);

            _PlayButton.EventLoad();
            _CloseButton.EventLoad();
            _FullScreenButton.EventLoad();

            _ContentControl.MouseLeftButtonDown += _ContentControl_MouseLeftButtonDown;
            _ContentControl.MouseLeftButtonUp += _ContentControl_MouseLeftButtonUp;
            _ContentControl.PreviewMouseDoubleClick += _ContentControl_PreviewMouseDoubleClick;
        }

        private void _ContentControl_PreviewMouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            DoubleClick(sender, e);
        }

        private void _ContentControl_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            _IsDoubleClick = false;
            if (_MouseDown2)
            {
                SetVisibleBottom();
            }
            _MouseDown2 = false;
        }

        void SetVisibleBottom()
        {
            if (_BottomPanel.Visibility != System.Windows.Visibility.Visible)
            {
                _BottomPanel.Visibility = System.Windows.Visibility.Visible;
            }
            _EndTime = DateTime.Now;
        }

        public DateTime _EndTime { get; set; }

        private void _ContentControl_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (_IsDoubleClick) return;
            _MouseDown2 = true;
        }

        bool _MouseDown2 { get; set; }

        ImageTextButton _CloseButton { get; set; }

        ImageTextButton _FullScreenButton { get; set; }

        public bool IsFullScreen { get; set; }


        System.Windows.Controls.Primitives.Popup _Popup { get; set; }

        void OpenFullScreen()
        {
            IsFullScreen = true;
            _FullScreenButton.SetLabelText("还原");
            ShowPopup(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height);
        }

        public void SetFullScreen()
        {
            try
            {
                if (IsFullScreen)
                {
                    CloseFullScreen();
                }
                else
                {
                    OpenFullScreen();
                }
            }
            catch (Exception ex)
            {
                LoggerProxy.Exception(Name, "DoubleClick", ex);
            }
        }

        bool _IsDoubleClick { get; set; }

        void DoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            _IsDoubleClick = true;
            SetFullScreen();

            if (SysncFullScreen != null) SysncFullScreen(IsFullScreen);
        }

        void CloseFullScreen()
        {
            if (_PictureBoxPlayer != null)
            {
                _PictureBoxPlayer.IsFullScreen = false;
                _PictureBoxPlayer.ClosePictureBoxFullScreen();
                IsFullScreen = false;
            }
            else if (_Popup != null)
            {
                _Popup.Child = null;
                _Grid.Children.Add(_Grid2);
                _Popup.IsOpen = false;
                _Popup = null;
                IsFullScreen = false;

                _FullScreenButton.SetLabelText("全屏");
            }
        }

        public Action<bool> SysncFullScreen { get; set; }

        void ShowPopup(double width, double height)
        {
            if (_PictureBoxPlayer != null)
            {
                _PictureBoxPlayer.IsFullScreen = true;
                _PictureBoxPlayer.SetPictureBoxFullSreen();
            }
            else
            {
                _Grid.Children.Clear();
                _Popup = new System.Windows.Controls.Primitives.Popup();
                _Popup.Child = _Grid2;
                _Popup.IsOpen = true;

                SetPopupWidthHeight(width, height);
            }
        }

        void SetPopupWidthHeight(double width, double height)
        {
            System.Windows.DependencyObject parent = _Popup.Child;

            do
            {
                parent = System.Windows.Media.VisualTreeHelper.GetParent(parent);

                if (parent != null && parent.ToString() == "System.Windows.Controls.Primitives.PopupRoot")
                {
                    var element = parent as System.Windows.FrameworkElement;

                    element.Width = width;
                    element.Height = height;

                    break;
                }
            }
            while (parent != null);
        }
    }
}
